﻿/*
 * 作者：郝伟老师
 * 使用：静态日志写入类。
 * 说明： 
 * 一个基于多线程和缓冲机制的高性能日志记录类。提供了以下五个静态函数。
 * AddLog(int logType, string methondInfo, string[] args)
 * Logger.SystemInfo(params string[] args)
 * Logger.Debug(params string[] args)
 * Logger.Error(params string[] args)
 * Logger.Exception(params string[] args)
 * 分别表示一般日志添加和四个专用类型添加。
 * 为了提交效率，日志先写入缓冲，每秒检测一次，如果有数据则进行一次本地并发的写操作。
 * 注意：当程序退出时，请调用 IDisposable 接口，以保存缓冲中的数据。
 * 
 * 【历史更新记录】
 * 2019/06/14   V1.0    初步建立此类。 
 * 
 * 
 */

using System;
using System.Diagnostics;

namespace WindGoes6.Data.Logs
{
    /// <summary>
    /// 一个基于多线程的日志记录类。提供了以下五个静态函数。
    /// AddLog(int logType, string methondInfo, string[] args)
    /// Logger.SystemInfo(params string[] args)
    /// Logger.Debug(params string[] args)
    /// Logger.Error(params string[] args)
    /// Logger.Exception(params string[] args)
    /// 分别表示一般日志添加和四个专用类型添加。
    /// 为了提交效率，日志先写入缓冲，每秒检测一次，如果有数据则进行一次本地并发的写操作。
    /// 注意：当程序退出时，请调用 IDisposable 接口，以保存缓冲中的数据。
    /// </summary>
    public class Logger :IDisposable
    { 
        static LogManager logManager;

        /// <summary>
        /// 需要保存的日志的名称。
        /// </summary>
        public static void SetLogFilePath(string filepath) {
            if (logManager != null)
                logManager.LogFilePath = filepath;
        }

        /// <summary>
        /// 获得调用函数的类名和方法。有坑提醒：默认层数为2层，从而获得
        /// TargetMethod.InvokeMethon.TraceMethodName 中的TargetMethod的信息。
        /// </summary>
        /// <returns></returns>
        static string TraceMethodName(int skipSteps = 2)
        {
            string info = "";
            // 获得上N级函数调用的相关信息。  
            StackFrame st = new StackFrame(skipSteps, true);
            info += string.Format("{1}.{2}@{3}",
                st.GetFileName(),                       // 文件名
                st.GetMethod().DeclaringType.FullName,  // 类全名
                st.GetMethod().Name,                    // 方法名
                st.GetFileLineNumber());                // 所在行号

            return info;
        }

        /// <summary>
        /// 结束时调用。
        /// </summary>
        public void Dispose()
        {
            if(logManager != null)
            {
                logManager.WriteLogsToFile();
                logManager = null;
            }
        }

        /// <summary>
        /// 添加一般类型日志。
        /// </summary>
        /// <param name="logType">The type of this log.</param>
        /// <param name="methondInfo">Method information.</param>
        /// <param name="args">The arguments of this log.</param>
        public static void AddLog(int logType, string methondInfo, string[] args)
        {
            if (logManager == null)
            {
                logManager = new LogManager();
                logManager.Start();
            }
            logManager.AddLog(logType, methondInfo, args);
        }

        /// <summary>
        /// Save logs into a file.
        /// </summary>
        /// <param name="logType"></param>
        /// <param name="args"></param>
        public static void Log(int logType, params string[] args)
        {
            AddLog(logType, TraceMethodName(), args);
        }

        /// <summary>
        /// Log system information.
        /// </summary>
        /// <param name="args"></param>
        public static void SystemInfo(params string[] args)
        {
            AddLog(LogType.SystemInfo_1001, TraceMethodName(), args);
        }

        /// <summary>
        /// Log debug messages.
        /// </summary>
        /// <param name="args">arguments.</param>
        public static void Debug(params string[] args)
        {
            AddLog(LogType.Debug_3001, TraceMethodName(), args);
        }

        /// <summary>
        /// Log exception messages.
        /// </summary>
        /// <param name="args">arguments.</param>
        public static void Exception(params string[] args)
        {
            AddLog(LogType.Exception_2001, TraceMethodName(), args);
        }


        /// <summary>
        /// Log errors.
        /// </summary>
        /// <param name="args">arguments.</param>
        public static void Error(params string[] args)
        {
            AddLog(LogType.Error_4001, TraceMethodName(), args);
        }
    }
}
